/*******************************************************************************
 * FilePath    : /Software/Examples_Ble_MS1642/ble_app_peripheral_uart_led/Src/BSP/UART.c
 * Version     : 1.0
 * Brief       :
 * Author      : AndrewHu
 * Company     : Shanghai MacroGiga Electronics CO.,Ltd
 * Email       : Hubinbo@macrogiga.com
 * Date        : 2020-03-24 15:42:28
 * LastEditors : AndrewHu
 * LastEditTime: 2023-11-14 16:58:21
 * Description :
 ******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <Includes.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

#define MAX_SIZE 200
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

static u8 txBuf[MAX_SIZE], rxBuf[MAX_SIZE];
static u16 txIn = 0, rxIn = 0;   // 待发送、接收待取出数据的Index
static u16 txOut = 0, rxOut = 0; // 已发送、接收并取出数据的Index
static u8 rxTimeOut = 0;         // 接收超时，判断串口数据是否发送完成
static u8 txEn = 0;              // 发送使能标志
/* Private function ----------------------------------------------------------*/
/* extern --------------------------------------------------------------------*/
/*******************************************************************************
 * Function    : Fun_Uart_Init
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2023-11-14 18:10:54
 * Description : 串口初始化
 ******************************************************************************/
void Fun_Uart_Init(void)
{
    UART_HandleTypeDef UartHandle;

    UartHandle.Instance = UARTx;

    UartHandle.Init.BaudRate = 115200;
    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits = UART_STOPBITS_1;
    UartHandle.Init.Parity = UART_PARITY_NONE;

    UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle.Init.Mode = UART_MODE_TX_RX;

#ifdef DEF_OVERSAMPLING_8
    UartHandle.Init.OverSampling = UART_OVERSAMPLING_8;
#endif

    if (HAL_UART_DeInit(&UartHandle) != HAL_OK)
    { // 恢复默认
        Error_Handler();
    }
    if (HAL_UART_Init(&UartHandle) != HAL_OK)
    { // 初始化
        Error_Handler();
    }

    UARTx->CR1 |= USART_CR1_RXNEIE | USART_CR1_TCIE;
}
/*******************************************************************************
 * Function    : UART0_INT_Callback
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2020-03-24 18:10:54
 * Description : 串口中断
 ******************************************************************************/
void UART_INT_Callback(void)
{
    if (UARTx->SR & UART_IT_RXNE) // 串口接收中断
    {
        AHL_Data_ArryIn(rxBuf, MAX_SIZE, &rxIn, UARTx->DR);
        rxTimeOut = 0x00;
    }
    else if (UARTx->SR & UART_IT_TC) // 串口发送中断
    {
        UARTx->SR &= ~UART_IT_TC;
        if (txIn != txOut)
        {
            UARTx->DR = AHL_Data_ArryOut(txBuf, MAX_SIZE, &txOut);
        }
        else
        {
            txEn = 0; // 发送完成
        }
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Byte
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2020-03-24 18:28:52
 * Description : 串口发送一个字节
 ******************************************************************************/
void Uart_Send_Byte(u8 data)
{
    AHL_Data_ArryIn(txBuf, MAX_SIZE, &txIn, data);
}
/*******************************************************************************
 * Function    : Uart_Send_String
 * Brief       :
 * Parameter   : {u8*} data-字符串或数组
 * Returns     : {u8} len-长度
 * Date        : 2020-03-24 18:48:47
 * Description : 发送一个字符串或数组
 ******************************************************************************/
void Uart_Send_String(u8 *data, u8 len)
{
    u8 i;
    for (i = 0; i < len; i++)
    {
        AHL_Data_ArryIn(txBuf, MAX_SIZE, &txIn, *data);
        data++;
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Byte2Ascii
 * Brief       :
 * Parameter   : {u8} data-待发送数据
 * Returns     :
 * Date        : 2020-03-24 18:30:09
 * Description : 串口发送一个字节（转换成ASCII）
 ******************************************************************************/
void Uart_Send_Byte2Ascii(u8 data)
{
    Uart_Send_Byte(AHL_Data_Hex2Ascii_4bit(data >> 4));
    Uart_Send_Byte(AHL_Data_Hex2Ascii_4bit(data));
}
/*******************************************************************************
 * Function    : Uart_Send_Array
 * Brief       :
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-数组长度
 * Returns     :
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（原始数据）
 ******************************************************************************/
void Uart_Send_Array(u8 *data, u8 len)
{
    u8 i;
    for (i = 0; i < len; i++)
    {
        Uart_Send_Byte(data[i]);
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Array_R
 * Brief       :
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-数组长度
 * Returns     :
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（原始数据），倒序
 ******************************************************************************/
void Uart_Send_Array_R(u8 *data, u8 len)
{
    u8 i;
    for (i = len; i != 0; i--)
    {
        Uart_Send_Byte(data[i - 1]);
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Array2Ascii
 * Brief       :
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-数组长度
 * Parameter   : {u8} space-是否空格做间隔
 * Returns     :
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（转成ASCII）
 ******************************************************************************/
void Uart_Send_Array2Ascii(u8 *data, u8 len, u8 space)
{
    u8 i;
    for (i = 0; i < len; i++)
    {
        Uart_Send_Byte2Ascii(data[i]);
        if (space)
            Uart_Send_Byte(' '); // 插入空格
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Array2Ascii_R
 * Brief       :
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-数组长度
 * Parameter   : {u8} space-是否空格做间隔
 * Returns     :
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（转成ASCII），倒序
 ******************************************************************************/
void Uart_Send_Array2Ascii_R(u8 *data, u8 len, u8 space)
{
    u8 i;
    for (i = len; i != 0; i--)
    {
        Uart_Send_Byte2Ascii(data[i - 1]);
        if (space)
            Uart_Send_Byte(' '); // 插入空格
    }
}
/*******************************************************************************
 * Function    : GetUartTxFlag
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2020-03-25 15:16:44
 * Description : 获取串口发送状态
 ******************************************************************************/
u8 GetUartTxFlag(void)
{
    return txEn;
}
/*******************************************************************************
 * Function    : GetUartStatus
 * Brief       : 获取串口工作状态
 * Parameter   :
 * Returns     :
 * Date        : 2020-03-25 15:16:44
 * Description :
 ******************************************************************************/
u8 GetUartStatus(void)
{
    if ((txEn != 0) || (txOut != txIn) || (rxOut != rxIn))
        return 1; // 串口有数据待处理
    else
        return 0; // 串口空闲
}
/*******************************************************************************
 * Function    : Uart_Send_Data
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2020-03-24 19:02:59
 * Description : 串口数据发送判断
 ******************************************************************************/
void Uart_Send_Data(void)
{
    if ((txOut != txIn) && (txEn == 0))
    { // 有数据待发送，发送使能标志未置1
        // Exit2Uart();
        txEn = 1;
        UARTx->DR = AHL_Data_ArryOut(txBuf, MAX_SIZE, &txOut);
    }
}
/*******************************************************************************
 * Function    : BleSendData
 * Brief       :
 * Parameter   : {u8} overflag-串口数据是否接收完成
 * Returns     :
 * Date        : 2020-03-23 17:36:40
 * Description : 从串口接受数组中取出数据给蓝牙发送
 ******************************************************************************/
static void BleSendData(u8 overflag)
{
    u8 i;
    u8 bleUartData[20] = {0};

    if (overflag == 0)
    { // 数据尚未接收完，但已达到20个字节
        if (rxIn >= rxOut)
        { // 数据未溢出数组
            if ((rxIn - rxOut) < 20)
                return; // 没有达到20个字节
        }
        else
        { // 数据溢出数组
            if ((MAX_SIZE - rxOut + rxIn) < 20)
                return; // 没有达到20个字节
        }

        // 接收到20个byte数据
    }

    // 达到了20个字节，或接收完成
    i = 0;
    while (rxIn != rxOut) // 有待取出数据
    {
        bleUartData[i] = AHL_Data_ArryOut(rxBuf, MAX_SIZE, &rxOut);

        i++;
        if (i >= 20)
            break; // 数据长度超过20，只发送20个字节
    }

    SendNotifyData(bleUartData, i);
}
/*******************************************************************************
 * Function    : Uart_Receive_Data
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2020-03-24 19:01:52
 * Description : 接收数据
 ******************************************************************************/
void Uart_Receive_Data(void)
{
    if (rxOut == rxIn)
    { // 没有接收到数据
        rxTimeOut = 0x00;
        return;
    }

    if (rxTimeOut < 0x02)
    { // 串口正在接收数据
        // 串口有数据时会一直清零
        rxTimeOut++;

        if (GetConnectedStatus())
        { // 蓝牙连接
            // 透传模式，接收到的数据超过20个字节，取出数据
            BleSendData(0);
        }
    }
    else
    { // 串口数据接收完成(超时)，取出数据
        if (!GetConnectedStatus())
        { // 蓝牙未连接
            rxOut = rxIn;
            Printf_ConnectStatus(0);
        }
        else
        { // 蓝牙连接
            // 透传模式,数据接收完成
            BleSendData(1);
        }
        rxTimeOut = 0x00;
    }
}
/*******************************************************************************
 * Function    : Fun_Uart_Run
 * Brief       :
 * Parameter   :
 * Returns     :
 * Date        : 2020-03-24 19:02:19
 * Description : 串口执行
 ******************************************************************************/
void Fun_Uart_Run(void)
{
    Uart_Send_Data();
    Uart_Receive_Data();
}
